package com.bank.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bank.dto.Result;
import com.bank.entity.UserInfo;
import com.bank.exception.BankException;
import com.bank.mapper.UserInfoMapper;
import com.bank.service.UserInfoService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVPrinter;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.io.StringWriter;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.regex.Pattern;

/**
 * 客户信息服务实现类
 * 实现客户信息相关的业务逻辑处理
 * 
 * @author 开发团队
 * @version 1.0.0
 * @since 2025-06-19
 */
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class UserInfoServiceImpl implements UserInfoService {

    @Autowired
    private UserInfoMapper userInfoMapper;

    /**
     * 身份证号正则表达式
     */
    private static final Pattern PID_PATTERN = Pattern.compile("^[0-9]{17}[0-9Xx]$");

    /**
     * 手机号正则表达式
     */
    private static final Pattern PHONE_PATTERN = Pattern.compile("^[0-9]{11}$");

    @Override
    public Result<UserInfo> addCustomer(UserInfo userInfo) {
        log.info("开始新增客户信息：{}", userInfo);
        
        try {
            // 验证客户信息
            Result<Void> validateResult = validateCustomerInfo(userInfo);
            if (!validateResult.isSuccess()) {
                return Result.error(validateResult.getMessage());
            }

            // 检查身份证号是否已存在
            Result<Boolean> pidExistsResult = checkPidExists(userInfo.getPid(), null);
            if (pidExistsResult.getData()) {
                return Result.error("身份证号已存在，请检查后重试");
            }

            // 检查联系电话是否已存在
            Result<Boolean> phoneExistsResult = checkTelephoneExists(userInfo.getTelephone(), null);
            if (phoneExistsResult.getData()) {
                return Result.error("联系电话已存在，请检查后重试");
            }

            // 插入客户信息
            int result = userInfoMapper.insert(userInfo);
            if (result > 0) {
                log.info("客户信息新增成功，客户ID：{}", userInfo.getCustomerId());
                return Result.success("客户信息新增成功", userInfo);
            } else {
                return Result.error("客户信息新增失败");
            }
        } catch (Exception e) {
            log.error("新增客户信息异常：", e);
            throw new BankException("新增客户信息失败：" + e.getMessage());
        }
    }

    @Override
    public Result<String> deleteCustomer(Integer customerId) {
        log.info("开始删除客户信息，客户ID：{}", customerId);
        
        try {
            if (customerId == null) {
                return Result.badRequest("客户ID不能为空");
            }

            // 检查客户是否存在
            UserInfo userInfo = userInfoMapper.selectById(customerId);
            if (userInfo == null) {
                return Result.notFound("客户信息不存在");
            }

            // 检查是否有关联的银行卡
            int cardCount = userInfoMapper.countCardsByCustomerId(customerId);
            if (cardCount > 0) {
                return Result.error("该客户还有关联的银行卡，无法删除");
            }

            // 删除客户信息
            int result = userInfoMapper.deleteById(customerId);
            if (result > 0) {
                log.info("客户信息删除成功，客户ID：{}", customerId);
                return Result.success("客户信息删除成功");
            } else {
                return Result.error("客户信息删除失败");
            }
        } catch (Exception e) {
            log.error("删除客户信息异常：", e);
            throw new BankException("删除客户信息失败：" + e.getMessage());
        }
    }

    @Override
    public Result<String> batchDeleteCustomers(List<Integer> customerIds) {
        log.info("开始批量删除客户信息，客户ID列表：{}", customerIds);
        
        try {
            if (customerIds == null || customerIds.isEmpty()) {
                return Result.badRequest("客户ID列表不能为空");
            }

            // 检查每个客户是否有关联的银行卡
            for (Integer customerId : customerIds) {
                int cardCount = userInfoMapper.countCardsByCustomerId(customerId);
                if (cardCount > 0) {
                    UserInfo userInfo = userInfoMapper.selectById(customerId);
                    String customerName = userInfo != null ? userInfo.getCustomerName() : "未知";
                    return Result.error("客户【" + customerName + "】还有关联的银行卡，无法删除");
                }
            }

            // 批量删除客户信息
            int result = userInfoMapper.batchDeleteByIds(customerIds);
            if (result > 0) {
                log.info("批量删除客户信息成功，删除数量：{}", result);
                return Result.success("批量删除客户信息成功，删除数量：" + result);
            } else {
                return Result.error("批量删除客户信息失败");
            }
        } catch (Exception e) {
            log.error("批量删除客户信息异常：", e);
            throw new BankException("批量删除客户信息失败：" + e.getMessage());
        }
    }

    @Override
    public Result<UserInfo> updateCustomer(UserInfo userInfo) {
        log.info("开始修改客户信息：{}", userInfo);
        
        try {
            if (userInfo.getCustomerId() == null) {
                return Result.badRequest("客户ID不能为空");
            }

            // 检查客户是否存在
            UserInfo existingUser = userInfoMapper.selectById(userInfo.getCustomerId());
            if (existingUser == null) {
                return Result.notFound("客户信息不存在");
            }

            // 验证客户信息
            Result<Void> validateResult = validateCustomerInfo(userInfo);
            if (!validateResult.isSuccess()) {
                return Result.error(validateResult.getMessage());
            }

            // 检查身份证号是否已存在（排除当前客户）
            Result<Boolean> pidExistsResult = checkPidExists(userInfo.getPid(), userInfo.getCustomerId());
            if (pidExistsResult.getData()) {
                return Result.error("身份证号已存在，请检查后重试");
            }

            // 检查联系电话是否已存在（排除当前客户）
            Result<Boolean> phoneExistsResult = checkTelephoneExists(userInfo.getTelephone(), userInfo.getCustomerId());
            if (phoneExistsResult.getData()) {
                return Result.error("联系电话已存在，请检查后重试");
            }

            // 更新客户信息
            int result = userInfoMapper.updateById(userInfo);
            if (result > 0) {
                log.info("客户信息修改成功，客户ID：{}", userInfo.getCustomerId());
                return Result.success("客户信息修改成功", userInfo);
            } else {
                return Result.error("客户信息修改失败");
            }
        } catch (Exception e) {
            log.error("修改客户信息异常：", e);
            throw new BankException("修改客户信息失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional(readOnly = true)
    public Result<UserInfo> getCustomerById(Integer customerId) {
        try {
            if (customerId == null) {
                return Result.badRequest("客户ID不能为空");
            }

            UserInfo userInfo = userInfoMapper.selectById(customerId);
            if (userInfo == null) {
                return Result.notFound("客户信息不存在");
            }

            return Result.success(userInfo);
        } catch (Exception e) {
            log.error("查询客户信息异常：", e);
            throw new BankException("查询客户信息失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional(readOnly = true)
    public Result<UserInfo> getCustomerByPid(String pid) {
        try {
            if (StringUtils.isBlank(pid)) {
                return Result.badRequest("身份证号不能为空");
            }

            UserInfo userInfo = userInfoMapper.selectByPid(pid);
            if (userInfo == null) {
                return Result.notFound("客户信息不存在");
            }

            return Result.success(userInfo);
        } catch (Exception e) {
            log.error("根据身份证号查询客户信息异常：", e);
            throw new BankException("查询客户信息失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional(readOnly = true)
    public Result<List<UserInfo>> getCustomersByNameLike(String customerName) {
        try {
            if (StringUtils.isBlank(customerName)) {
                return Result.badRequest("客户姓名不能为空");
            }

            List<UserInfo> userInfoList = userInfoMapper.selectByCustomerNameLike(customerName);
            return Result.success(userInfoList);
        } catch (Exception e) {
            log.error("根据客户姓名模糊查询异常：", e);
            throw new BankException("查询客户信息失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional(readOnly = true)
    public Result<List<UserInfo>> getCustomersByTelephoneLike(String telephone) {
        try {
            if (StringUtils.isBlank(telephone)) {
                return Result.badRequest("联系电话不能为空");
            }

            List<UserInfo> userInfoList = userInfoMapper.selectByTelephoneLike(telephone);
            return Result.success(userInfoList);
        } catch (Exception e) {
            log.error("根据联系电话模糊查询异常：", e);
            throw new BankException("查询客户信息失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional(readOnly = true)
    public Result<List<UserInfo>> getCustomersByCreateTimeRange(LocalDateTime startTime, LocalDateTime endTime) {
        try {
            if (startTime == null || endTime == null) {
                return Result.badRequest("开始时间和结束时间不能为空");
            }

            if (startTime.isAfter(endTime)) {
                return Result.badRequest("开始时间不能晚于结束时间");
            }

            List<UserInfo> userInfoList = userInfoMapper.selectByCreateTimeRange(startTime, endTime);
            return Result.success(userInfoList);
        } catch (Exception e) {
            log.error("根据创建时间范围查询异常：", e);
            throw new BankException("查询客户信息失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional(readOnly = true)
    public Result<IPage<UserInfo>> getCustomersPage(Page<UserInfo> page, String customerName, String pid, 
                                                   String telephone, LocalDateTime startTime, LocalDateTime endTime) {
        try {
            if (startTime != null && endTime != null && startTime.isAfter(endTime)) {
                return Result.badRequest("开始时间不能晚于结束时间");
            }

            IPage<UserInfo> result = userInfoMapper.selectPageWithConditions(page, customerName, pid, telephone, startTime, endTime);
            return Result.success(result);
        } catch (Exception e) {
            log.error("分页查询客户信息异常：", e);
            throw new BankException("查询客户信息失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional(readOnly = true)
    public Result<List<UserInfo>> getAllCustomers() {
        try {
            List<UserInfo> userInfoList = userInfoMapper.selectList(null);
            return Result.success(userInfoList);
        } catch (Exception e) {
            log.error("查询所有客户信息异常：", e);
            throw new BankException("查询客户信息失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional(readOnly = true)
    public Result<Boolean> checkPidExists(String pid, Integer excludeCustomerId) {
        try {
            if (StringUtils.isBlank(pid)) {
                return Result.badRequest("身份证号不能为空");
            }

            int count = userInfoMapper.countByPid(pid, excludeCustomerId);
            return Result.success(count > 0);
        } catch (Exception e) {
            log.error("检查身份证号是否存在异常：", e);
            throw new BankException("检查身份证号失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional(readOnly = true)
    public Result<Boolean> checkTelephoneExists(String telephone, Integer excludeCustomerId) {
        try {
            if (StringUtils.isBlank(telephone)) {
                return Result.badRequest("联系电话不能为空");
            }

            int count = userInfoMapper.countByTelephone(telephone, excludeCustomerId);
            return Result.success(count > 0);
        } catch (Exception e) {
            log.error("检查联系电话是否存在异常：", e);
            throw new BankException("检查联系电话失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional(readOnly = true)
    public Result<Integer> getCustomerCount() {
        try {
            int count = userInfoMapper.selectTotalCount();
            return Result.success(count);
        } catch (Exception e) {
            log.error("获取客户统计信息异常：", e);
            throw new BankException("获取客户统计信息失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional(readOnly = true)
    public Result<String> exportCustomersToCSV() {
        try {
            List<UserInfo> userInfoList = userInfoMapper.selectList(null);
            
            StringWriter stringWriter = new StringWriter();
            CSVFormat csvFormat = CSVFormat.DEFAULT.withHeader(
                "客户编号", "客户姓名", "身份证号", "联系电话", "联系地址", "创建时间", "更新时间"
            );
            
            try (CSVPrinter csvPrinter = new CSVPrinter(stringWriter, csvFormat)) {
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                
                for (UserInfo userInfo : userInfoList) {
                    csvPrinter.printRecord(
                        userInfo.getCustomerId(),
                        userInfo.getCustomerName(),
                        userInfo.getPid(),
                        userInfo.getTelephone(),
                        userInfo.getAddress(),
                        userInfo.getCreateTime() != null ? userInfo.getCreateTime().format(formatter) : "",
                        userInfo.getUpdateTime() != null ? userInfo.getUpdateTime().format(formatter) : ""
                    );
                }
            }
            
            log.info("客户信息导出成功，导出数量：{}", userInfoList.size());
            return Result.success("客户信息导出成功", stringWriter.toString());
        } catch (IOException e) {
            log.error("导出客户信息到CSV异常：", e);
            throw new BankException("导出客户信息失败：" + e.getMessage());
        }
    }

    @Override
    public Result<Void> validateCustomerInfo(UserInfo userInfo) {
        if (userInfo == null) {
            return Result.badRequest("客户信息不能为空");
        }

        if (StringUtils.isBlank(userInfo.getCustomerName())) {
            return Result.badRequest("客户姓名不能为空");
        }

        if (userInfo.getCustomerName().length() > 50) {
            return Result.badRequest("客户姓名长度不能超过50个字符");
        }

        if (StringUtils.isBlank(userInfo.getPid())) {
            return Result.badRequest("身份证号不能为空");
        }

        if (!PID_PATTERN.matcher(userInfo.getPid()).matches()) {
            return Result.badRequest("身份证号格式不正确，应为18位数字或17位数字+1位数字/字母");
        }

        if (StringUtils.isBlank(userInfo.getTelephone())) {
            return Result.badRequest("联系电话不能为空");
        }

        if (!PHONE_PATTERN.matcher(userInfo.getTelephone()).matches()) {
            return Result.badRequest("联系电话格式不正确，应为11位数字");
        }

        if (StringUtils.isNotBlank(userInfo.getAddress()) && userInfo.getAddress().length() > 200) {
            return Result.badRequest("联系地址长度不能超过200个字符");
        }

        return Result.success();
    }
}
